// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package image_group_api_impl

import (
	"context"
	"time"

	"gitcode.com/openseaotter/so_proto_gen_go.git/image_group_api"
	"gitcode.com/openseaotter/so_server/config"
	"gitcode.com/openseaotter/so_server/storage"
)

type ImageGroupApiImpl struct {
	image_group_api.UnimplementedImageGroupApiServer
}

func (apiImpl *ImageGroupApiImpl) Create(ctx context.Context, req *image_group_api.CreateRequest) (*image_group_api.CreateResponse, error) {
	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}
	projectId := ""
	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_group_api.CreateResponse{
				Code:   image_group_api.CreateResponse_CODE_NO_REMOTE,
				ErrMsg: "鉴权服务器不存在",
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_group_api.CreateResponse{
				Code:   image_group_api.CreateResponse_CODE_NO_PERMISSION,
				ErrMsg: "用户不存在",
			}, nil
		}
		if !remoteMember.MemberIsAdmin {
			return &image_group_api.CreateResponse{
				Code:   image_group_api.CreateResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
		projectId = remoteMember.ProjectId
	}

	if req.PermInfo == nil {
		req.PermInfo = &image_group_api.ImageGroupPerm{
			PublicGroup:        false,
			MemberPerm:         map[string]*image_group_api.ImageGroupMemberList{},
			PullSecretNameList: []string{},
			PushSecretNameList: []string{},
		}
	}
	if req.PermInfo.MemberPerm == nil {
		req.PermInfo.MemberPerm = map[string]*image_group_api.ImageGroupMemberList{}
	}

	//检查是否已经存在分组
	exist, err := storage.ImageGroupDao.Exist(ctx, req.GroupName)
	if err != nil {
		return nil, err
	}
	if exist {
		return &image_group_api.CreateResponse{
			Code:   image_group_api.CreateResponse_CODE_GROUP_NAME_DUP,
			ErrMsg: "镜像分组已经存在",
		}, nil
	}
	if projectId != "" {
		_, ok := req.PermInfo.MemberPerm[projectId]
		if !ok {
			req.PermInfo.MemberPerm[projectId] = &image_group_api.ImageGroupMemberList{
				MemberUserIdForView:   []string{},
				MemberUserIdForRemove: []string{},
			}
		}
	}

	//调整验证密钥列表
	err = apiImpl.adjustSecretOfPerm(ctx, req.PermInfo)
	if err != nil {
		return nil, err
	}
	nowTime := time.Now().UnixMilli()
	err = storage.ImageGroupDao.Insert(ctx, &image_group_api.ImageGroupInfo{
		GroupName:      req.GroupName,
		PermInfo:       req.PermInfo,
		ImageInfoCount: 0,
		CreateTime:     nowTime,
		UpdateTime:     nowTime,
	})
	if err != nil {
		return nil, err
	}
	return &image_group_api.CreateResponse{
		Code: image_group_api.CreateResponse_CODE_OK,
	}, nil
}

func (apiImpl *ImageGroupApiImpl) UpdatePerm(ctx context.Context, req *image_group_api.UpdatePermRequest) (*image_group_api.UpdatePermResponse, error) {
	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}
	projectId := ""
	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_group_api.UpdatePermResponse{
				Code:   image_group_api.UpdatePermResponse_CODE_NO_REMOTE,
				ErrMsg: "鉴权服务器不存在",
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_group_api.UpdatePermResponse{
				Code:   image_group_api.UpdatePermResponse_CODE_NO_PERMISSION,
				ErrMsg: "用户不存在",
			}, nil
		}
		if !remoteMember.MemberIsAdmin {
			return &image_group_api.UpdatePermResponse{
				Code:   image_group_api.UpdatePermResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
		projectId = remoteMember.ProjectId
	}

	groupInfo, err := storage.ImageGroupDao.Get(ctx, req.GroupName)
	if err != nil {
		return &image_group_api.UpdatePermResponse{
			Code:   image_group_api.UpdatePermResponse_CODE_NO_GROUP,
			ErrMsg: "镜像分组不存在",
		}, nil
	}

	if groupInfo.PermInfo == nil {
		groupInfo.PermInfo = &image_group_api.ImageGroupPerm{
			PublicGroup:        false,
			MemberPerm:         map[string]*image_group_api.ImageGroupMemberList{},
			PullSecretNameList: []string{},
			PushSecretNameList: []string{},
		}
	}
	if groupInfo.PermInfo.MemberPerm == nil {
		groupInfo.PermInfo.MemberPerm = map[string]*image_group_api.ImageGroupMemberList{}
	}

	if projectId == "" {
		groupInfo.PermInfo = req.PermInfo
	} else {
		prjPerm, ok := req.PermInfo.MemberPerm[projectId]
		if ok {
			groupInfo.PermInfo.MemberPerm[projectId] = prjPerm
		} else {
			groupInfo.PermInfo.MemberPerm[projectId] = &image_group_api.ImageGroupMemberList{
				MemberUserIdForView:   []string{},
				MemberUserIdForRemove: []string{},
			}
		}
	}
	//调整验证密钥列表
	err = apiImpl.adjustSecretOfPerm(ctx, req.PermInfo)
	if err != nil {
		return nil, err
	}

	groupInfo.UpdateTime = time.Now().UnixMilli()
	err = storage.ImageGroupDao.Update(ctx, groupInfo)
	if err != nil {
		return nil, err
	}
	return &image_group_api.UpdatePermResponse{
		Code: image_group_api.UpdatePermResponse_CODE_OK,
	}, nil
}

func (apiImpl *ImageGroupApiImpl) Remove(ctx context.Context, req *image_group_api.RemoveRequest) (*image_group_api.RemoveResponse, error) {
	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}

	groupInfo, err := storage.ImageGroupDao.Get(ctx, req.GroupName)
	if err != nil { //记录不存在
		return &image_group_api.RemoveResponse{
			Code: image_group_api.RemoveResponse_CODE_OK,
		}, nil
	}

	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_group_api.RemoveResponse{
				Code:   image_group_api.RemoveResponse_CODE_NO_REMOTE,
				ErrMsg: "鉴权服务器不存在",
			}, nil
		}
		remoteUser, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_group_api.RemoveResponse{
				Code:   image_group_api.RemoveResponse_CODE_NO_PERMISSION,
				ErrMsg: "用户不存在",
			}, nil
		}

		if !remoteUser.MemberIsAdmin { //只有管理员可以删除镜像分组
			return &image_group_api.RemoveResponse{
				Code:   image_group_api.RemoveResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
	}

	//检查是否存在image记录

	if groupInfo.ImageInfoCount > 0 {
		return &image_group_api.RemoveResponse{
			Code:   image_group_api.RemoveResponse_CODE_HAS_IMAGE_INFO,
			ErrMsg: "镜像分组中存在未删除镜像",
		}, nil
	}
	err = storage.ImageGroupDao.Remove(ctx, req.GroupName)
	if err != nil {
		return nil, err
	}
	return &image_group_api.RemoveResponse{
		Code: image_group_api.RemoveResponse_CODE_OK,
	}, nil
}

func (apiImpl *ImageGroupApiImpl) List(ctx context.Context, req *image_group_api.ListRequest) (*image_group_api.ListResponse, error) {
	emptyList := []*image_group_api.ImageGroupInfo{}

	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}
	memberUserId := ""
	projectId := ""
	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_group_api.ListResponse{
				Code:      image_group_api.ListResponse_CODE_NO_REMOTE,
				ErrMsg:    "鉴权服务器不存在",
				GroupList: emptyList,
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_group_api.ListResponse{
				Code:      image_group_api.ListResponse_CODE_NO_PERMISSION,
				ErrMsg:    "没有权限",
				GroupList: emptyList,
			}, nil
		}
		//管理员可以看到所有镜像分组
		if !remoteMember.MemberIsAdmin {
			memberUserId = remoteMember.MemberUserId
		}
		projectId = remoteMember.ProjectId
	}
	groupList, err := storage.ImageGroupDao.List(ctx)
	if err != nil {
		return nil, err
	}
	newGroupList := []*image_group_api.ImageGroupInfo{}
	for _, group := range groupList {
		if memberUserId == "" {
			newGroupList = append(newGroupList, group)
		} else {
			match := false
			memberListPerm := group.PermInfo.MemberPerm[projectId]
			if memberListPerm != nil {
				for _, viewUserId := range memberListPerm.MemberUserIdForView {
					if viewUserId == memberUserId {
						match = true
						break
					}
				}
			}

			if match || group.PermInfo.PublicGroup {
				newGroupList = append(newGroupList, group)
			}
		}
	}

	count := len(newGroupList)
	start := int(req.Offset)
	end := int(req.Offset + req.Limit)
	if start >= count {
		return &image_group_api.ListResponse{
			Code:       image_group_api.ListResponse_CODE_OK,
			TotalCount: uint32(count),
			GroupList:  emptyList,
		}, nil
	}

	if end > count {
		end = count
	}

	//只留下相关项目的权限
	if projectId != "" {
		for i := start; i < end; i++ {
			if newGroupList[i].PermInfo == nil {
				newGroupList[i].PermInfo = &image_group_api.ImageGroupPerm{
					PublicGroup:        false,
					MemberPerm:         map[string]*image_group_api.ImageGroupMemberList{},
					PullSecretNameList: []string{},
					PushSecretNameList: []string{},
				}
			}
			if newGroupList[i].PermInfo.MemberPerm == nil {
				newGroupList[i].PermInfo.MemberPerm = map[string]*image_group_api.ImageGroupMemberList{}
			}

			prjPerm, ok := newGroupList[i].PermInfo.MemberPerm[projectId]
			newGroupList[i].PermInfo.MemberPerm = map[string]*image_group_api.ImageGroupMemberList{}
			if ok {
				newGroupList[i].PermInfo.MemberPerm[projectId] = prjPerm
			}
		}
	}

	return &image_group_api.ListResponse{
		Code:       image_group_api.ListResponse_CODE_OK,
		TotalCount: uint32(count),
		GroupList:  newGroupList[start:end],
	}, nil
}

func (apiImpl *ImageGroupApiImpl) Get(ctx context.Context, req *image_group_api.GetRequest) (*image_group_api.GetResponse, error) {
	emptyInfo := &image_group_api.ImageGroupInfo{}

	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return nil, err
	}

	memberUserId := ""
	projectId := ""
	if cfg.SuperToken != "" && req.AccessToken == cfg.SuperToken {
		//do nothing
	} else {
		remoteCfg, ok := cfg.GetRemote(req.RemoteId)
		if !ok {
			return &image_group_api.GetResponse{
				Code:   image_group_api.GetResponse_CODE_NO_REMOTE,
				ErrMsg: "鉴权服务器不存在",
				Group:  emptyInfo,
			}, nil
		}
		remoteMember, _, err := storage.QueryMember(ctx, remoteCfg.RemoteAddr, req.AccessToken)
		if err != nil {
			return &image_group_api.GetResponse{
				Code:   image_group_api.GetResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Group:  emptyInfo,
			}, nil
		}
		//管理员可以看到所有镜像分组
		if !remoteMember.MemberIsAdmin {
			memberUserId = remoteMember.MemberUserId
		}
		projectId = remoteMember.ProjectId
	}

	group, err := storage.ImageGroupDao.Get(ctx, req.GroupName)
	if err != nil {
		return &image_group_api.GetResponse{
			Code:   image_group_api.GetResponse_CODE_NO_GROUP,
			ErrMsg: "镜像分组不存在",
			Group:  emptyInfo,
		}, nil
	}
	if memberUserId == "" {
		return &image_group_api.GetResponse{
			Code:  image_group_api.GetResponse_CODE_OK,
			Group: group,
		}, nil
	} else {
		match := false
		memberListPerm := group.PermInfo.MemberPerm[projectId]
		if memberListPerm != nil {
			for _, viewUserId := range memberListPerm.MemberUserIdForView {
				if viewUserId == memberUserId {
					match = true
					break
				}
			}
		}

		if !match && !group.PermInfo.PublicGroup {
			return &image_group_api.GetResponse{
				Code:   image_group_api.GetResponse_CODE_NO_GROUP,
				ErrMsg: "镜像分组不存在",
				Group:  emptyInfo,
			}, nil
		} else {
			if group.PermInfo == nil {
				group.PermInfo = &image_group_api.ImageGroupPerm{
					PublicGroup:        false,
					MemberPerm:         map[string]*image_group_api.ImageGroupMemberList{},
					PullSecretNameList: []string{},
					PushSecretNameList: []string{},
				}
			}
			if group.PermInfo.MemberPerm == nil {
				group.PermInfo.MemberPerm = map[string]*image_group_api.ImageGroupMemberList{}
			}

			prjPerm, ok := group.PermInfo.MemberPerm[projectId]
			group.PermInfo.MemberPerm = map[string]*image_group_api.ImageGroupMemberList{}
			if ok {
				group.PermInfo.MemberPerm[projectId] = prjPerm
			}
			return &image_group_api.GetResponse{
				Code:  image_group_api.GetResponse_CODE_OK,
				Group: group,
			}, nil
		}
	}
}

func (apiImpl *ImageGroupApiImpl) adjustSecretOfPerm(ctx context.Context, permInfo *image_group_api.ImageGroupPerm) error {
	secretList, err := storage.AuthSecretDao.List(ctx)
	if err != nil {
		return err
	}
	nameMap := map[string]bool{}

	for _, secret := range secretList {
		nameMap[secret.Username] = true
	}

	newPullSecretNameList := []string{}
	newPushSecretNameList := []string{}

	for _, name := range permInfo.PullSecretNameList {
		if nameMap[name] {
			newPullSecretNameList = append(newPullSecretNameList, name)
		}
	}
	for _, name := range permInfo.PushSecretNameList {
		if nameMap[name] {
			newPushSecretNameList = append(newPushSecretNameList, name)
		}
	}
	permInfo.PullSecretNameList = newPullSecretNameList
	permInfo.PushSecretNameList = newPushSecretNameList
	return nil
}
